package aTurk2;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Vector;

public class Problem implements Parameters{
	private ArrayList<Integer> xArray;
	private ArrayList<Double> pArray;
	public int cost;
	public int id;
	public int realVal;
	public double expectancy;
	public double resVal;
	public int revenue;
	public int moneySpent;
	
	public Problem(String line){
		xArray=new ArrayList<Integer>();
		pArray=new ArrayList<Double>();
		StringTokenizer st=new StringTokenizer(line, ",");
		id=Integer.parseInt(st.nextToken());
		cost=Integer.parseInt(st.nextToken());
		realVal=Integer.parseInt(st.nextToken());
		while(st.hasMoreElements()){
			xArray.add(Integer.parseInt(st.nextToken()));
			pArray.add(Double.parseDouble(st.nextToken()));
		}
		//set expectancy
		setExpectancy();
		//set Reservation-Value
		setReservationValue();
	}
	
	//cTor for known realValue problem
	public Problem(int identifyer,int c,int _realVal){
		this.id=identifyer;
		cost=c;
		realVal=_realVal;
		xArray=new ArrayList<Integer>();
		xArray.add(realVal-1);
		xArray.add(2);
		xArray.add(TOTAL_L-(realVal+1));
		
		pArray=new ArrayList<Double>();
		pArray.add(0.00001);
		pArray.add(0.99998);
		pArray.add(0.00001);
		setExpectancy();
		setReservationValue();
	}
	
	public void setExpectancy(){
		double tmp=0;
		int sumInterval=0;
		int newInterval=0;
		for(int i=0;i<pArray.size();i++){
			newInterval=xArray.get(i);
			tmp=tmp+(pArray.get(i)*(((newInterval)/2)+sumInterval));
			sumInterval+=newInterval;
		}
		expectancy=tmp;
	}
	/**
	 * 
	 * @param x
	 * for the probability pricing strategy
	 */
	public void setProbabilityResVal(int x){
		double tmp=probabilitySmallerThan(x);
		resVal=(((MAX_QUERY_TIME-cost)/(double)MAX_QUERY_TIME)*COST_WEIGHT) + (tmp*(1-COST_WEIGHT));
	}
	private double probabilitySmallerThan(int resVal){
		boolean exit_flag=true;
		int sumX=xArray.get(0),idX=0;
		//running until the interval is bigger than ResVal
		while(exit_flag){
			if(resVal>=TOTAL_L){
				return 0;
			}
			if(sumX>=resVal)
				exit_flag=false;
			else{
				idX++;
				sumX+=xArray.get(idX);
			}
		}
		//calculating inside the interval of ResVal
		double p=0;
		for(int i=0;i<idX;++i){
			p+=pArray.get(i);
		}
		double base=resVal-(sumX-xArray.get(idX));
		double height=pArray.get(idX)/xArray.get(idX);
		p=p+(base*height);
		
		return (p);
	}
	/**
	 * 
	 */
	public void setReservationValue(){
		 Vector<Double> Rvec =new Vector<Double>();
		 resVal=TOTAL_L;
		 ArrayList<Integer>tmpX=new ArrayList<Integer>();
		 tmpX.add(0);
		 for(int i=0;i<xArray.size();i++){
			tmpX.add(tmpX.get(i)+xArray.get(i));
		 }
        for(int k=1; k<=pArray.size();k++){
            Rvec.add(calcOneResValue(pArray, tmpX, cost, k));
        }
         //check which rectangle Ri is in
        for(int i=0;i<Rvec.size();i++){
            if(Rvec.get(i)<=tmpX.get(i+1)&&(Rvec.get(i)>=tmpX.get(i)))
                resVal=Rvec.get(i);
        }
	}
	 public double calcOneResValue(ArrayList<Double> P, ArrayList<Integer> Xvec,double cost,int j){
         double R_value=0;
         double sideA=0;
         for(int k=1;k<j;k++){
             double Pi=0;
             for(int i=0;i<k-1;i++){
                 Pi=Pi+P.get(i);
             }
             sideA=sideA+Pi*(Xvec.get(k)-Xvec.get(k-1));
             double frac=(P.get(k-1)*(Math.pow(Xvec.get(k), 2)-2*Xvec.get(k)*Xvec.get(k-1)+Math.pow(Xvec.get(k-1), 2)));
             frac=frac/(2*(Xvec.get(k)-Xvec.get(k-1)));
             sideA=sideA+frac;
         }
         double pi=0;
         for(int i=0;i<j-1;i++)
             pi=pi+P.get(i);
         double C=(-cost*2*(Xvec.get(j)-Xvec.get(j-1))+(2*sideA*(Xvec.get(j)-Xvec.get(j-1)))+(-2*Xvec.get(j-1)*pi*(Xvec.get(j)-Xvec.get(j-1)))+(-P.get(j-1)*Math.pow(Xvec.get(j-1), 2))+(2*P.get(j-1)*Math.pow(Xvec.get(j-1), 2)));
         double A=P.get(j-1);
         double B=pi*2*(Xvec.get(j)-Xvec.get(j-1)) - (2*P.get(j-1)*Xvec.get(j-1));
         
         R_value=((-1*B)+ Math.sqrt(Math.pow(B, 2)-4*A*C))/(2*A);
         return R_value;
     }
	 

		public String toExcelFormat(){
			StringBuilder sb=new StringBuilder();
			sb.append(id);
			sb.append(",");
			sb.append(cost);
			sb.append(",");
			sb.append(realVal);
			
			DecimalFormat currency = new DecimalFormat("#0.000000");
			for(int i=0;i<xArray.size();++i){
				sb.append(",");
				sb.append(xArray.get(i));
				sb.append(",");
				sb.append(currency.format(pArray.get(i)));
			}
		
			return sb.toString();
		}
		

		public String toSpecialFormat(){
			StringBuilder sb=new StringBuilder();
			sb.append(id);
			sb.append(":");
			sb.append(cost);
			sb.append(":");
			sb.append(realVal);
			sb.append(":");
			sb.append("0");
			sb.append(":");
			sb.append("0");
			
			DecimalFormat currency = new DecimalFormat("#0.000000");
			for(int i=0;i<xArray.size();++i){
				sb.append(":");
				sb.append(xArray.get(i));
				sb.append(":");
				sb.append(currency.format(pArray.get(i)));
			}
			
			return sb.toString();
		}
		
		public double probabilitySmaller(int resVal){
			boolean exit_flag=true;
			int sumX=xArray.get(0),idX=0;
			//running until the interval is bigger than ResVal
			while(exit_flag){
				if(resVal>=TOTAL_L){
					return 0;
				}
				if(sumX>=resVal)
					exit_flag=false;
				else{
					idX++;
					sumX+=xArray.get(idX);
				}
			}
			//calculating inside the interval of ResVal
			double p=0;
			for(int i=0;i<idX;++i){
				p+=pArray.get(i);
			}
			double base=resVal-(sumX-xArray.get(idX));
			double height=pArray.get(idX)/xArray.get(idX);
			p=p+(base*height);
			
			return (1-p);
		}
}
